<template>
  <div class="sc-tooltip"
  v-on="tooltipEventsOuter"
  style="display: inline-block;"
  ref="tooltipRef"
  >
    <div class="sc-tooltip-trigger" ref="triggerRef"  style="display: inline-block;"
    v-on="tooltipEventsInner"
    >
      <slot name="trigger"></slot>
    </div>
    <Transition :name="transition">
      <div class="sc-tooltip-display" ref="displayRef" v-if="visibleFlag" style="display: inline-block;">
        <slot name="display"></slot>
      </div>
    </Transition>
  </div>
</template>

<script lang="ts">
export default {
   name: 'ScTooltip',
}
</script>
<script lang="ts" setup>
import {computed, ref,watch,reactive} from 'vue';
// 引入popperjs中的创建函数createPopper和popper关联变量类型Instance
import {createPopper} from '@popperjs/core';
import type{Instance} from '@popperjs/core';
// 引入props类型接、事件类型接口
import type{tooltipProps,tooltipEmits,tooltipExpose} from "./types";
// 引入点击元素外部关闭元素的函数
import userClickOutside from '../../hooks/userClickOutside'
// 获取props值并设置默认值
const props = withDefaults(defineProps<tooltipProps>(),{
  placeType:'right',
  triggerType:'click',
  manual:false,
  transition:"fade"
});

// 定义展示情况的变量
const visibleFlag = ref<boolean>(false);
// 定义修改展示情况的函数
function changeVisibleFlag(flag?:string) {
  if(flag == '0') {
    visibleFlag.value = false;
  } else if(flag == '1') {
    visibleFlag.value = true;
  } else {
    visibleFlag.value = !visibleFlag.value;
  }
}

// 定义事件对象
// 写法一
// const tooltipEventsInner = computed(():Record<string,() => void> => {

//   if(props.triggerType == 'click'){
//     return {
//       'click':()=>changeVisibleFlag()
//     }
//   } else {
//     return {
//       'mouseenter': ()=>changeVisibleFlag('1')
//     }
//   }
// });
// const tooltipEventsOuter= computed(():Record<string,() => void> => {
//   if(props.triggerType == 'click') {
//     return {}
//   } else {
//     return {
//       'mouseleave':()=>changeVisibleFlag('0')
//     }
//   }
// });
// 写法二
const tooltipEventsOuter = reactive((():Record<string,() => void> => {
  if(props.manual || props.triggerType == 'click') {
    return {}
  } else {
    return {
    'mouseleave':()=>changeVisibleFlag('0')
  }
  }
})());
const tooltipEventsInner = reactive((():Record<string,() => void> => {
  if(props.manual) {
    return {};
  } else {
    if(props.triggerType == 'click') {
      return {
        'click':()=>changeVisibleFlag()
      }
    } else {
      return {
        'mouseenter':()=>changeVisibleFlag('1')
      }
    }
  }
})());
// 写法三
// const tooltipEventsOuter:Record<string,() => void> = reactive({});
// const tooltipEventsInner:Record<string,() => void> = reactive({});
// attachEvents();
// // 管理事件绑定的函数
// function attachEvents() {
//   if(!props.manual) {
//     if(props.triggerType == 'click') {
//       tooltipEventsInner['click'] = ()=>changeVisibleFlag();
//     } else {
//       tooltipEventsInner['mouseenter'] = ()=>changeVisibleFlag('1');
//       tooltipEventsOuter['mouseleave'] = ()=>changeVisibleFlag('0');
//     }

//   }
// }

// 定义组件事件
const emits = defineEmits<tooltipEmits>();
// 获取触发区和展示区并声明关联变量tooltipInstance
const triggerRef = ref<HTMLElement>();
const displayRef = ref<HTMLElement>();
let tooltipInstance:Instance | null = null;
const popperOptions = computed(() => {
  return {
    placement:props.placeType,
    ...props.popperOptions
  }
});
// 监听展示flag，执行关联操作
watch(() => visibleFlag.value,(newFlag) => {
  emits('visible-change',newFlag,'成功');
  // 执行popper操作
  if(newFlag) {
    if(triggerRef.value && displayRef.value) {
      tooltipInstance = createPopper(triggerRef.value,displayRef.value,popperOptions.value);
    }
  } else {
    tooltipInstance?.destroy();
  }

},{flush:'post'});


// 获取tooltipRef
const tooltipRef = ref<HTMLElement>();
userClickOutside(tooltipRef,() => {
  if(props.triggerType=="click" && displayRef.value && !props.manual) {
    changeVisibleFlag('0');
  }
});

defineExpose<tooltipExpose>({
  'show':() => props.manual ? changeVisibleFlag('1') : () => {},
  'hide':() => props.manual ? changeVisibleFlag('0') : () => {}
});
</script>
<style scoped>
@import './style.css';
</style>
